"""
实时性能监控服务
"""
import asyncio
import psutil
import time
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta, date
from collections import deque, defaultdict
import structlog

from core.config import get_settings
from services.alerts.alert_management_service import AlertManagementService

logger = structlog.get_logger(__name__)


class PerformanceMetrics:
    """性能指标数据类"""
    
    def __init__(self):
        self.timestamp = datetime.now()
        self.cpu_usage = 0.0
        self.memory_usage = 0.0
        self.gpu_usage = 0.0
        self.gpu_memory_usage = 0.0
        self.disk_usage = 0.0
        self.network_io = {"bytes_sent": 0, "bytes_recv": 0}
        self.processing_latency = 0.0
        self.frame_rate = 0.0
        self.active_streams = 0
        self.ai_processing_count = 0
        self.error_count = 0


class RealTimePerformanceMonitor:
    """实时性能监控器"""
    
    def __init__(self):
        self.settings = get_settings()
        self.alert_service = AlertManagementService()
        
        # 性能指标历史数据
        self.metrics_history = deque(maxlen=1000)  # 保留最近1000个数据点
        self.camera_metrics = defaultdict(lambda: deque(maxlen=100))  # 每个摄像头保留100个数据点
        self.ai_metrics = defaultdict(lambda: deque(maxlen=100))  # 每个AI算法保留100个数据点
        
        # 告警状态
        self.alert_states = {}
        self.last_alert_time = {}
        
        # 系统启动时间
        self.start_time = datetime.now()
        
        # 监控任务
        self.monitoring_task = None
        self.is_monitoring = False
    
    async def start_monitoring(self):
        """启动监控"""
        if self.is_monitoring:
            return
        
        self.is_monitoring = True
        self.monitoring_task = asyncio.create_task(self._monitoring_loop())
        logger.info("实时性能监控已启动")
    
    async def stop_monitoring(self):
        """停止监控"""
        self.is_monitoring = False
        if self.monitoring_task:
            self.monitoring_task.cancel()
            try:
                await self.monitoring_task
            except asyncio.CancelledError:
                pass
        logger.info("实时性能监控已停止")
    
    async def _monitoring_loop(self):
        """监控循环"""
        try:
            while self.is_monitoring:
                # 收集系统指标
                metrics = await self._collect_system_metrics()
                self.metrics_history.append(metrics)
                
                # 检查告警条件
                await self._check_alert_conditions(metrics)
                
                # 等待下一次收集
                await asyncio.sleep(self.settings.METRICS_COLLECTION_INTERVAL)
                
        except asyncio.CancelledError:
            logger.info("监控循环已取消")
        except Exception as e:
            logger.error("监控循环异常", error=str(e))
    
    async def _collect_system_metrics(self) -> PerformanceMetrics:
        """收集系统性能指标"""
        metrics = PerformanceMetrics()
        
        try:
            # CPU使用率
            metrics.cpu_usage = psutil.cpu_percent(interval=1)
            
            # 内存使用率
            memory = psutil.virtual_memory()
            metrics.memory_usage = memory.percent
            
            # 磁盘使用率
            disk = psutil.disk_usage('/')
            metrics.disk_usage = (disk.used / disk.total) * 100
            
            # 网络IO
            network = psutil.net_io_counters()
            metrics.network_io = {
                "bytes_sent": network.bytes_sent,
                "bytes_recv": network.bytes_recv
            }
            
            # GPU使用率（如果可用）
            try:
                import GPUtil
                gpus = GPUtil.getGPUs()
                if gpus:
                    gpu = gpus[0]  # 使用第一个GPU
                    metrics.gpu_usage = gpu.load * 100
                    metrics.gpu_memory_usage = gpu.memoryUtil * 100
            except ImportError:
                logger.debug("GPUtil未安装，跳过GPU监控")
            except Exception as e:
                logger.debug("GPU监控失败", error=str(e))
            
        except Exception as e:
            logger.error("收集系统指标失败", error=str(e))
        
        return metrics
    
    async def _check_alert_conditions(self, metrics: PerformanceMetrics):
        """检查告警条件"""
        try:
            thresholds = self.settings.PERFORMANCE_ALERT_THRESHOLD
            
            # 检查各项指标
            alerts_to_send = []
            
            if metrics.cpu_usage > thresholds["cpu_usage"]:
                alerts_to_send.append({
                    "type": "cpu_high",
                    "message": f"CPU使用率过高: {metrics.cpu_usage:.1f}%",
                    "severity": "warning" if metrics.cpu_usage < 95 else "critical",
                    "value": metrics.cpu_usage,
                    "threshold": thresholds["cpu_usage"]
                })
            
            if metrics.memory_usage > thresholds["memory_usage"]:
                alerts_to_send.append({
                    "type": "memory_high",
                    "message": f"内存使用率过高: {metrics.memory_usage:.1f}%",
                    "severity": "warning" if metrics.memory_usage < 90 else "critical",
                    "value": metrics.memory_usage,
                    "threshold": thresholds["memory_usage"]
                })
            
            if metrics.gpu_usage > thresholds["gpu_usage"]:
                alerts_to_send.append({
                    "type": "gpu_high",
                    "message": f"GPU使用率过高: {metrics.gpu_usage:.1f}%",
                    "severity": "warning" if metrics.gpu_usage < 98 else "critical",
                    "value": metrics.gpu_usage,
                    "threshold": thresholds["gpu_usage"]
                })
            
            if metrics.processing_latency > thresholds["processing_latency"]:
                alerts_to_send.append({
                    "type": "latency_high",
                    "message": f"处理延迟过高: {metrics.processing_latency:.2f}s",
                    "severity": "warning" if metrics.processing_latency < 5 else "critical",
                    "value": metrics.processing_latency,
                    "threshold": thresholds["processing_latency"]
                })
            
            # 发送告警
            for alert in alerts_to_send:
                await self._send_alert(alert)
                
        except Exception as e:
            logger.error("检查告警条件失败", error=str(e))
    
    async def _send_alert(self, alert: Dict[str, Any]):
        """发送告警"""
        try:
            alert_type = alert["type"]
            current_time = datetime.now()
            
            # 检查告警冷却时间
            if alert_type in self.last_alert_time:
                time_diff = current_time - self.last_alert_time[alert_type]
                if time_diff.total_seconds() < 300:  # 5分钟冷却时间
                    return
            
            # 创建告警
            await self.alert_service.create_system_alert(
                alert_type=alert_type,
                message=alert["message"],
                severity=alert["severity"],
                metadata={
                    "value": alert["value"],
                    "threshold": alert["threshold"],
                    "timestamp": current_time.isoformat()
                }
            )
            
            self.last_alert_time[alert_type] = current_time
            logger.warning("发送性能告警", alert=alert)
            
        except Exception as e:
            logger.error("发送告警失败", alert=alert, error=str(e))
    
    async def record_camera_metrics(self, camera_id: str, metrics: Dict[str, Any]):
        """记录摄像头性能指标"""
        try:
            camera_metric = {
                "timestamp": datetime.now(),
                "camera_id": camera_id,
                "frame_rate": metrics.get("frame_rate", 0),
                "processing_latency": metrics.get("processing_latency", 0),
                "error_count": metrics.get("error_count", 0),
                "stream_status": metrics.get("stream_status", "unknown")
            }
            
            self.camera_metrics[camera_id].append(camera_metric)
            
        except Exception as e:
            logger.error("记录摄像头指标失败", camera_id=camera_id, error=str(e))
    
    async def record_ai_metrics(self, algorithm: str, metrics: Dict[str, Any]):
        """记录AI算法性能指标"""
        try:
            ai_metric = {
                "timestamp": datetime.now(),
                "algorithm": algorithm,
                "processing_time": metrics.get("processing_time", 0),
                "accuracy": metrics.get("accuracy", 0),
                "throughput": metrics.get("throughput", 0),
                "error_count": metrics.get("error_count", 0)
            }
            
            self.ai_metrics[algorithm].append(ai_metric)
            
        except Exception as e:
            logger.error("记录AI指标失败", algorithm=algorithm, error=str(e))
    
    async def get_system_status(self) -> Dict[str, Any]:
        """获取系统状态"""
        try:
            if not self.metrics_history:
                return {"status": "no_data", "message": "暂无监控数据"}
            
            latest_metrics = self.metrics_history[-1]
            
            # 判断系统状态
            status = "healthy"
            if (latest_metrics.cpu_usage > 90 or 
                latest_metrics.memory_usage > 90 or 
                latest_metrics.gpu_usage > 95):
                status = "critical"
            elif (latest_metrics.cpu_usage > 80 or 
                  latest_metrics.memory_usage > 80 or 
                  latest_metrics.gpu_usage > 85):
                status = "warning"
            
            return {
                "status": status,
                "cpu_usage": latest_metrics.cpu_usage,
                "memory_usage": latest_metrics.memory_usage,
                "gpu_usage": latest_metrics.gpu_usage,
                "gpu_memory_usage": latest_metrics.gpu_memory_usage,
                "disk_usage": latest_metrics.disk_usage,
                "active_streams": latest_metrics.active_streams,
                "timestamp": latest_metrics.timestamp.isoformat()
            }
            
        except Exception as e:
            logger.error("获取系统状态失败", error=str(e))
            return {"status": "error", "message": str(e)}
    
    async def get_system_uptime(self) -> Dict[str, Any]:
        """获取系统运行时间"""
        try:
            uptime = datetime.now() - self.start_time
            
            return {
                "start_time": self.start_time.isoformat(),
                "uptime_seconds": int(uptime.total_seconds()),
                "uptime_formatted": str(uptime).split('.')[0]  # 去掉微秒
            }
            
        except Exception as e:
            logger.error("获取系统运行时间失败", error=str(e))
            return {}
    
    async def get_performance_metrics(self, start_time: datetime, end_time: datetime) -> Dict[str, Any]:
        """获取指定时间范围的性能指标"""
        try:
            filtered_metrics = [
                m for m in self.metrics_history 
                if start_time <= m.timestamp <= end_time
            ]
            
            if not filtered_metrics:
                return {"message": "指定时间范围内无数据"}
            
            # 计算统计信息
            cpu_values = [m.cpu_usage for m in filtered_metrics]
            memory_values = [m.memory_usage for m in filtered_metrics]
            gpu_values = [m.gpu_usage for m in filtered_metrics]
            
            return {
                "data_points": len(filtered_metrics),
                "cpu_usage": {
                    "avg": sum(cpu_values) / len(cpu_values),
                    "max": max(cpu_values),
                    "min": min(cpu_values)
                },
                "memory_usage": {
                    "avg": sum(memory_values) / len(memory_values),
                    "max": max(memory_values),
                    "min": min(memory_values)
                },
                "gpu_usage": {
                    "avg": sum(gpu_values) / len(gpu_values) if gpu_values else 0,
                    "max": max(gpu_values) if gpu_values else 0,
                    "min": min(gpu_values) if gpu_values else 0
                },
                "time_series": [
                    {
                        "timestamp": m.timestamp.isoformat(),
                        "cpu_usage": m.cpu_usage,
                        "memory_usage": m.memory_usage,
                        "gpu_usage": m.gpu_usage
                    }
                    for m in filtered_metrics
                ]
            }
            
        except Exception as e:
            logger.error("获取性能指标失败", error=str(e))
            return {"error": str(e)}
    
    async def get_recent_alerts(self, severity: Optional[str] = None, limit: int = 100) -> List[Dict[str, Any]]:
        """获取最近的告警"""
        try:
            alerts = await self.alert_service.get_recent_system_alerts(severity, limit)
            return alerts
            
        except Exception as e:
            logger.error("获取最近告警失败", error=str(e))
            return []
    
    async def get_ai_performance_metrics(self, algorithm: Optional[str] = None) -> Dict[str, Any]:
        """获取AI算法性能指标"""
        try:
            if algorithm:
                if algorithm not in self.ai_metrics:
                    return {"message": f"算法 {algorithm} 无性能数据"}
                
                metrics = list(self.ai_metrics[algorithm])
                if not metrics:
                    return {"message": f"算法 {algorithm} 无性能数据"}
                
                # 计算统计信息
                processing_times = [m["processing_time"] for m in metrics]
                throughputs = [m["throughput"] for m in metrics]
                
                return {
                    "algorithm": algorithm,
                    "data_points": len(metrics),
                    "processing_time": {
                        "avg": sum(processing_times) / len(processing_times),
                        "max": max(processing_times),
                        "min": min(processing_times)
                    },
                    "throughput": {
                        "avg": sum(throughputs) / len(throughputs),
                        "max": max(throughputs),
                        "min": min(throughputs)
                    },
                    "recent_metrics": metrics[-10:]  # 最近10个数据点
                }
            else:
                # 返回所有算法的汇总信息
                summary = {}
                for alg, metrics in self.ai_metrics.items():
                    if metrics:
                        latest = metrics[-1]
                        summary[alg] = {
                            "data_points": len(metrics),
                            "latest_processing_time": latest["processing_time"],
                            "latest_throughput": latest["throughput"],
                            "latest_timestamp": latest["timestamp"].isoformat()
                        }
                
                return {"algorithms": summary}
                
        except Exception as e:
            logger.error("获取AI性能指标失败", error=str(e))
            return {"error": str(e)}
    
    async def get_ai_processing_statistics(self, start_time: datetime, end_time: datetime) -> Dict[str, Any]:
        """获取AI处理统计信息"""
        try:
            statistics = {}
            
            for algorithm, metrics in self.ai_metrics.items():
                filtered_metrics = [
                    m for m in metrics 
                    if start_time <= m["timestamp"] <= end_time
                ]
                
                if filtered_metrics:
                    total_processing = len(filtered_metrics)
                    total_errors = sum(m["error_count"] for m in filtered_metrics)
                    avg_processing_time = sum(m["processing_time"] for m in filtered_metrics) / total_processing
                    
                    statistics[algorithm] = {
                        "total_processing": total_processing,
                        "total_errors": total_errors,
                        "error_rate": (total_errors / total_processing * 100) if total_processing > 0 else 0,
                        "avg_processing_time": avg_processing_time
                    }
            
            return statistics
            
        except Exception as e:
            logger.error("获取AI处理统计失败", error=str(e))
            return {}
    
    async def get_resource_usage(self) -> Dict[str, Any]:
        """获取资源使用情况"""
        try:
            if not self.metrics_history:
                return {"message": "暂无监控数据"}
            
            latest = self.metrics_history[-1]
            
            return {
                "timestamp": latest.timestamp.isoformat(),
                "cpu": {
                    "usage_percent": latest.cpu_usage,
                    "core_count": psutil.cpu_count()
                },
                "memory": {
                    "usage_percent": latest.memory_usage,
                    "total_gb": round(psutil.virtual_memory().total / (1024**3), 2),
                    "available_gb": round(psutil.virtual_memory().available / (1024**3), 2)
                },
                "disk": {
                    "usage_percent": latest.disk_usage,
                    "total_gb": round(psutil.disk_usage('/').total / (1024**3), 2),
                    "free_gb": round(psutil.disk_usage('/').free / (1024**3), 2)
                },
                "gpu": {
                    "usage_percent": latest.gpu_usage,
                    "memory_usage_percent": latest.gpu_memory_usage
                },
                "network": latest.network_io
            }
            
        except Exception as e:
            logger.error("获取资源使用情况失败", error=str(e))
            return {"error": str(e)}
    
    async def generate_performance_report(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """生成性能报告"""
        try:
            report_type = config.get("type", "summary")
            duration_hours = config.get("duration_hours", 24)
            
            end_time = datetime.now()
            start_time = end_time - timedelta(hours=duration_hours)
            
            # 获取基础性能指标
            performance_metrics = await self.get_performance_metrics(start_time, end_time)
            
            # 获取AI统计
            ai_statistics = await self.get_ai_processing_statistics(start_time, end_time)
            
            # 获取告警信息
            alerts = await self.get_recent_alerts(limit=50)
            
            report = {
                "report_type": report_type,
                "time_range": {
                    "start_time": start_time.isoformat(),
                    "end_time": end_time.isoformat(),
                    "duration_hours": duration_hours
                },
                "system_performance": performance_metrics,
                "ai_statistics": ai_statistics,
                "alerts_summary": {
                    "total_alerts": len(alerts),
                    "critical_alerts": len([a for a in alerts if a.get("severity") == "critical"]),
                    "warning_alerts": len([a for a in alerts if a.get("severity") == "warning"])
                },
                "generated_at": datetime.now().isoformat()
            }
            
            return report
            
        except Exception as e:
            logger.error("生成性能报告失败", error=str(e))
            return {"error": str(e)}
    
    async def get_daily_report(self, report_date: date) -> Dict[str, Any]:
        """获取日报告"""
        try:
            start_time = datetime.combine(report_date, datetime.min.time())
            end_time = start_time + timedelta(days=1)
            
            # 生成日报告
            report_config = {
                "type": "daily",
                "duration_hours": 24
            }
            
            # 使用指定日期的时间范围
            performance_metrics = await self.get_performance_metrics(start_time, end_time)
            ai_statistics = await self.get_ai_processing_statistics(start_time, end_time)
            
            return {
                "report_date": report_date.isoformat(),
                "system_performance": performance_metrics,
                "ai_statistics": ai_statistics,
                "summary": {
                    "total_processing_time": sum(
                        stats.get("total_processing", 0) * stats.get("avg_processing_time", 0)
                        for stats in ai_statistics.values()
                    ),
                    "total_errors": sum(
                        stats.get("total_errors", 0)
                        for stats in ai_statistics.values()
                    )
                }
            }
            
        except Exception as e:
            logger.error("获取日报告失败", error=str(e))
            return {"error": str(e)}
    
    async def perform_health_check(self) -> Dict[str, Any]:
        """执行系统健康检查"""
        try:
            health_status = {
                "overall_status": "healthy",
                "checks": {},
                "timestamp": datetime.now().isoformat()
            }
            
            # 检查系统资源
            system_status = await self.get_system_status()
            health_status["checks"]["system_resources"] = {
                "status": system_status["status"],
                "details": system_status
            }
            
            # 检查监控服务
            health_status["checks"]["monitoring_service"] = {
                "status": "healthy" if self.is_monitoring else "error",
                "details": {
                    "is_running": self.is_monitoring,
                    "data_points": len(self.metrics_history)
                }
            }
            
            # 检查告警服务
            try:
                await self.alert_service.get_recent_system_alerts(limit=1)
                health_status["checks"]["alert_service"] = {
                    "status": "healthy",
                    "details": {"connection": "ok"}
                }
            except Exception as e:
                health_status["checks"]["alert_service"] = {
                    "status": "error",
                    "details": {"error": str(e)}
                }
            
            # 确定整体状态
            check_statuses = [check["status"] for check in health_status["checks"].values()]
            if "error" in check_statuses:
                health_status["overall_status"] = "error"
            elif "warning" in check_statuses:
                health_status["overall_status"] = "warning"
            
            return health_status
            
        except Exception as e:
            logger.error("系统健康检查失败", error=str(e))
            return {
                "overall_status": "error",
                "error": str(e),
                "timestamp": datetime.now().isoformat()
            }
    
    async def optimize_system_performance(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """优化系统性能"""
        try:
            optimization_actions = []
            
            # 获取当前系统状态
            system_status = await self.get_system_status()
            
            # 基于当前状态提供优化建议
            if system_status.get("cpu_usage", 0) > 80:
                optimization_actions.append({
                    "action": "reduce_processing_load",
                    "description": "降低处理负载，减少并发处理的摄像头数量",
                    "priority": "high"
                })
            
            if system_status.get("memory_usage", 0) > 80:
                optimization_actions.append({
                    "action": "clear_cache",
                    "description": "清理缓存，释放内存空间",
                    "priority": "medium"
                })
            
            if system_status.get("gpu_usage", 0) > 90:
                optimization_actions.append({
                    "action": "optimize_batch_size",
                    "description": "优化AI批处理大小，提高GPU利用效率",
                    "priority": "high"
                })
            
            # 如果没有发现问题，提供一般性优化建议
            if not optimization_actions:
                optimization_actions.append({
                    "action": "system_healthy",
                    "description": "系统运行正常，无需特殊优化",
                    "priority": "info"
                })
            
            return {
                "current_status": system_status,
                "optimization_actions": optimization_actions,
                "timestamp": datetime.now().isoformat()
            }
            
        except Exception as e:
            logger.error("系统性能优化失败", error=str(e))
            return {"error": str(e)}


# 全局性能监控器实例
performance_monitor = RealTimePerformanceMonitor()


def get_performance_monitor() -> RealTimePerformanceMonitor:
    """获取性能监控器实例"""
    return performance_monitor